package common;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Serializable;
import java.net.Socket;
import java.util.ArrayList;

import server.Posizione;

import client.Client;
import client.ClientThreadAscoltaRisposta;


public class SocketPerServerInterface implements ServerInterface{

	private BufferedReader bufferedReader;
	private BufferedWriter bufferedWriter;
	private Client client;
	private Socket socket;
	private ClientThreadAscoltaRisposta t;

	public SocketPerServerInterface(Client client){
		socket= client.getSocket();
		this.client=client;
		try {
			bufferedReader=new BufferedReader(new InputStreamReader(socket.getInputStream()));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		try {
			bufferedWriter=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
		
	
	public BufferedReader getBufferedReader() {
		return bufferedReader;
	}
	public void setBufferedReader(BufferedReader bufferedReader) {
		this.bufferedReader = bufferedReader;
	}
	public ClientThreadAscoltaRisposta getT() {
		return t;
	}
	public void setT(ClientThreadAscoltaRisposta t) {
		this.t = t;
	}


	@Override
	public String creaUtente(String user, String pass)throws ComandiException, IOException{
		
		//invio messaggio a server
		String mess="@creaUtente,user="+user+",pass="+pass;
		
		bufferedWriter.write(mess);
		bufferedWriter.newLine();
		bufferedWriter.flush();
		System.out.println(socket+" ---> "+mess);
	
		//ricevo messaggio da server
		String risp=ricezioneMess();
		
		if(risp.equals("@ok"))
			return "ok";
		else if(risp.equals("@no,"+ComandiException.USERNAME_OCCUPATO))
			throw new ComandiException(ComandiException.USERNAME_OCCUPATO);	
		return null;
	}

	@Override
	public String login(String user, String pass, ClientInterface client) throws ComandiException, IOException {
		//invio messaggio a server
		String mess="@login,user="+user+",pass="+pass;
		System.out.println(socket+" ---> "+mess);
		bufferedWriter.write(mess);
		bufferedWriter.newLine();
		bufferedWriter.flush();
	
		//ricevo messaggio da server
		String risp=ricezioneMess();
		
		String[] partiMess=risp.split("\\,");
		if(partiMess[0].equals("@ok")){
			
			return ""+partiMess[1];
		}else if(risp.equals("@no,"+ComandiException.AUTENTICAZIONE_FALLITA))
			
			throw new ComandiException(ComandiException.AUTENTICAZIONE_FALLITA);	
		
		return null;
	}

	@Override
	public String creaRazza(String token, String nomeRazza, char tipo) throws ComandiException, IOException {
		//invio messaggio a server
		String mess="@creaRazza,token="+token+",nome="+nomeRazza+",tipo="+tipo;
		System.out.println(socket+" ---> "+mess);
		bufferedWriter.write(mess);
		bufferedWriter.newLine();
		bufferedWriter.flush();
	
		//ricevo messaggio da server
		String risp=ricezioneMess();
		
		String[] partiMess=risp.split("\\,");
		if(partiMess[0].equals("@ok"))
			return "ok";
		else if(risp.equals("@no,"+ComandiException.NOME_RAZZA_OCCUPATO))
			throw new ComandiException(ComandiException.NOME_RAZZA_OCCUPATO);
		else if(risp.equals("@no,"+ComandiException.TOKEN_NON_VALIDO))
			throw new ComandiException(ComandiException.TOKEN_NON_VALIDO);
		else if(risp.equals("@no,"+ComandiException.COMANDO_NON_VALIDO))
			throw new ComandiException(ComandiException.COMANDO_NON_VALIDO);
		
		return null;
	}

	@Override
	public String accessoPartita(String token) throws ComandiException, IOException {
		//invio messaggio a server
		String mess="@accessoPartita,token="+token;
		System.out.println(socket+" ---> "+mess);
		bufferedWriter.write(mess);
		bufferedWriter.newLine();
		bufferedWriter.flush();
	
		//ricevo messaggio da server
		String risp=ricezioneMess();
		
		if(risp.equals("@ok"))
			return "ok";
		else if(risp.equals("@no,"+ComandiException.TOKEN_NON_VALIDO))
			throw new ComandiException(ComandiException.TOKEN_NON_VALIDO);	
		else if(risp.equals("@no,"+ComandiException.TROPPI_GIOCATORI))
			throw new ComandiException(ComandiException.TROPPI_GIOCATORI);	
		else if(risp.equals("@no,"+ComandiException.COMANDO_NON_VALIDO))
			throw new ComandiException(ComandiException.COMANDO_NON_VALIDO);
		return null;
	}

	@Override
	public String uscitaPartita(String token) throws ComandiException, IOException {
		//invio messaggio a server
		String mess="@uscitaPartita,token="+token;
		System.out.println(socket+" ---> "+mess);
		bufferedWriter.write(mess);
		bufferedWriter.newLine();
		bufferedWriter.flush();
	
		//ricevo messaggio da server
		String risp=ricezioneMess();
		
		if(risp.equals("@ok"))
			return "ok";
		else if(risp.equals("@no,"+ComandiException.TOKEN_NON_VALIDO))
			throw new ComandiException(ComandiException.TOKEN_NON_VALIDO);	
		
		return null;
	}

	@Override
	public String[] listaGiocatori(String token) throws ComandiException, IOException {
		//invio messaggio a server
		String mess="@listaGiocatori,token="+token;
		System.out.println(socket+" ---> "+mess);
		bufferedWriter.write(mess);
		bufferedWriter.newLine();
		bufferedWriter.flush();
	
		//ricevo messaggio da server
		String risp=ricezioneMess();
		
		String[] partiMess=risp.split("\\,");
		int len= partiMess.length-1;
		String[] lista= new String[len]; 
		if(partiMess[0].equals("@listaGiocatori")){
			for(int i=1;i<partiMess.length;i++){
				lista[i-1]=partiMess[i];
			}
			return lista;
		}
		else if(risp.equals("@no,"+ComandiException.TOKEN_NON_VALIDO))
			throw new ComandiException(ComandiException.TOKEN_NON_VALIDO);	
		
		return null;
	}

	@Override
	public String[] classifica(String token) throws ComandiException, IOException {
		//invio messaggio a server
		String mess="@classifica,token="+token;
		
		bufferedWriter.write(mess);
		bufferedWriter.newLine();
		bufferedWriter.flush();
		System.out.println(socket+" ---> "+mess);
	
		//ricevo messaggio da server
		String risp=ricezioneMess();
		
		String[] partiMess=risp.split("[\\{\\}]");
		
		if(risp.equals("@classifica")){
			String[] classifica=new String[0]; 
			return classifica;
		}
		else if(partiMess[0].equals("@classifica,")){
			//String[] p=partiMess[1].split("[{]|[}]");
			int len= partiMess.length-1;
			String[] classifica=new String[len]; 
			int j=0;
			for(int i=1;i<partiMess.length;i=i+2){
				String [] g=partiMess[i].split("\\,");
				String[] giocatore=new String[4];
				
					classifica[j]="Nome: "+g[0]+"  Razza: "+g[1]+"  Punti: "+g[2]+"  Ancora in vita: "+g[3];
					j++;
			}
			for(int i=0;i<classifica.length;i++){
				System.out.println(classifica[i]);
			}
			return classifica;
		}
		else if(risp.equals("@no,"+ComandiException.TOKEN_NON_VALIDO))
			throw new ComandiException(ComandiException.TOKEN_NON_VALIDO);	
		
		return null;
	}

	
	@Override
	public String logout(String token) throws ComandiException, IOException {
		//invio messaggio a server
		String mess="@logout,token="+token;
		
		bufferedWriter.write(mess);
		bufferedWriter.newLine();
		bufferedWriter.flush();
		System.out.println(socket+" ---> "+mess);
		
		//ricevo messaggio da server
		String risp=ricezioneMess();
		
		if(risp.equals("@ok"))
			return "ok";
		else if(risp.equals("@no,"+ComandiException.TOKEN_NON_VALIDO))
			throw new ComandiException(ComandiException.TOKEN_NON_VALIDO);	
		return null;
	}

	@Override
	public String[] mappaGenerale(String token) throws ComandiException, IOException {
		//invio messaggio a server
		String mess="@mappaGenerale,token="+token;
		
		bufferedWriter.write(mess);
		bufferedWriter.newLine();
		bufferedWriter.flush();
		System.out.println(socket+" ---> "+mess);
		
		//ricevo messaggio da server
		String risp=ricezioneMess();
		
		String[] partiMess=risp.split("\\,");
		int len= partiMess.length-1;
		if(partiMess[0].equals("@mappaGenerale")){
			String[] coordinateOrig=new String[2];	
			String[] coordinateMappa=new String[2];	
			
				String[] p=risp.split("[\\{\\}]");
				
				coordinateMappa = p[1].split("\\,");
				
				
				String[] mappaGen=new String[Integer.parseInt(""+coordinateMappa[1])+2];
				String[] righe=new String[Integer.parseInt(""+coordinateMappa[1])];
				righe=p[2].split("\\;");
				
				//for(int i =0;i<righe.length;i++){
				//	System.out.println(righe[i]);
				//}
				
				mappaGen[0]=coordinateMappa[0];
				mappaGen[1]=coordinateMappa[1];
				String[] caselle=new String[Integer.parseInt(""+coordinateMappa[0])*2+1];
				for(int i =2;i<righe.length+2;i++){
					
					caselle[i]="";
					
					caselle=righe[i-2].split("[\\[\\]]");
					mappaGen[i]="";
					for(int j=1;j<=caselle.length;j=j+2){
						
						mappaGen[i]=mappaGen[i]+caselle[j];
						
					}
				}
				
				//System.out.println("\nlettura mess MappaGen server->client:\n");
				//for(int i=0;i<mappaGen.length;i++){
					//System.out.println(mappaGen[i]);
				//}
				//System.out.println("\nlettura mess mappaGen server->client\n");
				
				return mappaGen;
		}else if(risp.equals("@no,"+ComandiException.TOKEN_NON_VALIDO))
			throw new ComandiException(ComandiException.TOKEN_NON_VALIDO);	
		else if(risp.equals("@no,"+ComandiException.NON_IN_PARTITA))
			throw new ComandiException(ComandiException.NON_IN_PARTITA);	
		
		return null;
}

	@Override
	public String[] listaDinosauri(String token) throws ComandiException, IOException {
		//invio messaggio a server
		String mess="@listaDinosauri,token="+token;
		
		bufferedWriter.write(mess);
		bufferedWriter.newLine();
		bufferedWriter.flush();
		System.out.println(socket+" ---> "+mess);
		
		//ricevo messaggio da server
		String risp=ricezioneMess();
		
		String[] partiMess=risp.split("\\,");
		int len= partiMess.length-1;
		String[]lista=new String[len];
		if(partiMess[0].equals("@listaDinosauri")){
			for(int i=1;i<partiMess.length;i++){
				lista[i-1]=partiMess[i];
			}
						
		return lista;
		}else if(risp.equals("@no,"+ComandiException.TOKEN_NON_VALIDO))
			throw new ComandiException(ComandiException.TOKEN_NON_VALIDO);	
		else if(risp.equals("@no,"+ComandiException.NON_IN_PARTITA))
			throw new ComandiException(ComandiException.NON_IN_PARTITA);	
		
		return null;
	}

	@Override
	public String[] vistaLocale(String token, String idDino)throws ComandiException, IOException {
		//invio messaggio a server
		String mess="@vistaLocale,token="+token+",idDino="+idDino;
		
		
		bufferedWriter.write(mess);
		bufferedWriter.newLine();
		bufferedWriter.flush();
		System.out.println(socket+" ---> "+mess);
		
		//ricevo messaggio da server
		String risp=ricezioneMess();
		
		String[] partiMess=risp.split("\\,");
		int len= partiMess.length-1;
		
		String[] coordinateOrig=new String[2];	
		String[] coordinateMappa=new String[2];	
		if(partiMess[0].equals("@vistaLocale")){
			String[] p=risp.split("[\\{\\}]");
			coordinateOrig = p[1].split("\\,");
			coordinateMappa = p[3].split("\\,");
			
			
			String[] vista=new String[Integer.parseInt(""+coordinateMappa[0])+4];
			String[] righe=new String[Integer.parseInt(""+coordinateMappa[0])];
			righe=p[4].split("\\;");
			
			for(int i =0;i<righe.length;i++){
				System.out.println(righe[i]);
				
			}
			vista[0]=coordinateOrig[0];
			vista[1]=coordinateOrig[1];
			vista[2]=coordinateMappa[0];
			vista[3]=coordinateMappa[1];
			String[] caselle;//=new String[Integer.parseInt(""+coordinateMappa[1])];
			
			for(int i =4;i<righe.length+4;i++){
				
				//caselle[i-4]="";
				
				caselle=righe[i-4].split("[\\[\\]]");
				String[] text= new String[Integer.parseInt(""+coordinateMappa[1])];
				int m=0;
				for(int l=0;l<caselle.length;l++){
					if(!caselle[l].equals("") && !caselle[l].equals(",")){
						text[m]=caselle[l];
						m++;
					}
					
				}
				vista[i]="";
				for(int j=0;j<text.length;j++){
					
					vista[i]=vista[i]+text[j]+";";
					
				}
				
			}
			
			//System.out.println("\nlettura messvistaLoc server->client:\n");
			//for(int i=0;i<vista.length;i++){
			//	System.out.println(vista[i]);
			//}
			//System.out.println("\nlettura messvistaLoc server->client\n");
		
			return vista;
		}else if(risp.equals("@no,"+ComandiException.TOKEN_NON_VALIDO))
			throw new ComandiException(ComandiException.TOKEN_NON_VALIDO);	
		else if(risp.equals("@no,"+ComandiException.NON_IN_PARTITA))
			throw new ComandiException(ComandiException.NON_IN_PARTITA);
		else if(risp.equals("@no,"+ComandiException.ID_NON_VALIDO))
			throw new ComandiException(ComandiException.ID_NON_VALIDO);
		
		
		
		return null;
	}

	@Override
	public String statoDinosauro(String token, String idDino)throws ComandiException, IOException {
		//invio messaggio a server
		String mess="@statoDinosauro,token="+token+",idDino="+idDino;
		
		bufferedWriter.write(mess);
		bufferedWriter.newLine();
		bufferedWriter.flush();
		System.out.println(socket+" ---> "+mess);
		
		//ricevo messaggio da server
		String risp=ricezioneMess();
		
		String[] partiMess=risp.split("\\,");
		int len= partiMess.length-1;
		String stato="";
		if(partiMess[0].equals("@statoDinosauro")){
			stato="Nome: "+partiMess[1]+"\n"+"Razza: "+partiMess[2]+"\n"+"Tipo: "+partiMess[3]+"\n"+partiMess[4]+","+partiMess[5]+"\n"+"Dimensione: "+partiMess[6]+"\n"+"Energia: "+partiMess[7]+"\n"+"Turni vissuti: "+partiMess[8]+"\n";
		
			return stato;
		}else if(risp.equals("@no,"+ComandiException.TOKEN_NON_VALIDO))
			throw new ComandiException(ComandiException.TOKEN_NON_VALIDO);	
		else if(risp.equals("@no,"+ComandiException.NON_IN_PARTITA))
			throw new ComandiException(ComandiException.NON_IN_PARTITA);
		else if(risp.equals("@no,"+ComandiException.ID_NON_VALIDO))
			throw new ComandiException(ComandiException.ID_NON_VALIDO);
	
		return null;
	}

	@Override
	public String movimento(String token, String idDino, int x, int y)throws ComandiException, IOException {
		//invio messaggio a server
		String mess="@muoviDinosauro,token="+token+",idDino="+idDino+",dest={"+x+","+y+"}";
		
		
		bufferedWriter.write(mess);
		bufferedWriter.newLine();
		bufferedWriter.flush();
		System.out.println(socket+" ---> "+mess);
		
		//ricevo messaggio da server
		String risp=ricezioneMess();
		
		if(risp.equals("@ok"))
			return "ok";
		else if	(risp.equals("@ok,v"))
			return "ok,v";
		else if	(risp.equals("@ok,p"))
			return "ok,p";
		else if(risp.equals("@no,"+ComandiException.TOKEN_NON_VALIDO))
			throw new ComandiException(ComandiException.TOKEN_NON_VALIDO);
		else if(risp.equals("@no,"+ComandiException.ID_NON_VALIDO))
			throw new ComandiException(ComandiException.ID_NON_VALIDO);
		else if(risp.equals("@no,"+ComandiException.DESTINAZIONE_NON_VALIDA))
			throw new ComandiException(ComandiException.DESTINAZIONE_NON_VALIDA);
		else if(risp.equals("@no,"+ComandiException.RAGGIUNTO_LIMITE_MOSSE_DINOSAURO))
			throw new ComandiException(ComandiException.RAGGIUNTO_LIMITE_MOSSE_DINOSAURO);
		else if(risp.equals("@no,"+ComandiException.MORTE_PER_INEDIA))
			throw new ComandiException(ComandiException.MORTE_PER_INEDIA);
		else if(risp.equals("@no,"+ComandiException.NON_IL_TUO_TURNO))
			throw new ComandiException(ComandiException.NON_IL_TUO_TURNO);
		else if(risp.equals("@no,"+ComandiException.NON_IN_PARTITA))
			throw new ComandiException(ComandiException.NON_IN_PARTITA);	
		else if(risp.equals("@no,"+ComandiException.FINE_PARTITA))
			throw new ComandiException(ComandiException.FINE_PARTITA);	
		
		return null;
	}

	@Override
	public String crescita(String token, String idDino) throws ComandiException, IOException {
		//invio messaggio a server
		String mess="@cresciDinosauro,token="+token+",idDino="+idDino;
		
		
		bufferedWriter.write(mess);
		bufferedWriter.newLine();
		bufferedWriter.flush();
		System.out.println(socket+" ---> "+mess);
		
		
		//ricevo messaggio da server
		String risp=ricezioneMess();
		
		if(risp.equals("@ok"))
			return "ok";
		else if(risp.equals("@no,"+ComandiException.TOKEN_NON_VALIDO))
			throw new ComandiException(ComandiException.TOKEN_NON_VALIDO);
		else if(risp.equals("@no,"+ComandiException.ID_NON_VALIDO))
			throw new ComandiException(ComandiException.ID_NON_VALIDO);
		else if(risp.equals("@no,"+ComandiException.RAGGIUNTO_LIMITE_MOSSE_DINOSAURO))
			throw new ComandiException(ComandiException.RAGGIUNTO_LIMITE_MOSSE_DINOSAURO);
		else if(risp.equals("@no,"+ComandiException.MORTE_PER_INEDIA))
			throw new ComandiException(ComandiException.MORTE_PER_INEDIA);
		else if(risp.equals("@no,"+ComandiException.NON_IL_TUO_TURNO))
			throw new ComandiException(ComandiException.NON_IL_TUO_TURNO);
		else if(risp.equals("@no,"+ComandiException.NON_IN_PARTITA))
			throw new ComandiException(ComandiException.NON_IN_PARTITA);
		else if(risp.equals("@no,"+ComandiException.FINE_PARTITA))
			throw new ComandiException(ComandiException.FINE_PARTITA);	
		return null;
	}

	@Override
	public String deposizioneUovo(String token, String idDino)throws ComandiException, IOException {
		//invio messaggio a server
		String mess="@deponiUovo,token="+token+",idDino="+idDino;
		
		bufferedWriter.write(mess);
		bufferedWriter.newLine();
		bufferedWriter.flush();
		System.out.println(socket+" ---> "+mess);
		
		
		//ricevo messaggio da server
		String risp=ricezioneMess();
		
		String[] partiMess=risp.split("\\,");
		if(partiMess[0].equals("@ok"))
			return partiMess[1];
		else if(risp.equals("@no,"+ComandiException.TOKEN_NON_VALIDO))
			throw new ComandiException(ComandiException.TOKEN_NON_VALIDO);
		else if(risp.equals("@no,"+ComandiException.ID_NON_VALIDO))
			throw new ComandiException(ComandiException.ID_NON_VALIDO);
		else if(risp.equals("@no,"+ComandiException.RAGGIUNTO_LIMITE_MOSSE_DINOSAURO))
			throw new ComandiException(ComandiException.RAGGIUNTO_LIMITE_MOSSE_DINOSAURO);
		else if(risp.equals("@no,"+ComandiException.MORTE_PER_INEDIA))
			throw new ComandiException(ComandiException.MORTE_PER_INEDIA);
		else if(risp.equals("@no,"+ComandiException.NON_IL_TUO_TURNO))
			throw new ComandiException(ComandiException.NON_IL_TUO_TURNO);
		else if(risp.equals("@no,"+ComandiException.NON_IN_PARTITA))
			throw new ComandiException(ComandiException.NON_IN_PARTITA);
		else if(risp.equals("@no,"+ComandiException.FINE_PARTITA))
			throw new ComandiException(ComandiException.FINE_PARTITA);	
		return null;
	}

	@Override
	public String confermaTurno(String token) throws ComandiException, IOException {
		//invio messaggio a server
		String mess="@confermaTurno,token="+token;
		
		bufferedWriter.write(mess);
		bufferedWriter.newLine();
		bufferedWriter.flush();
		System.out.println(socket+" ---> "+mess);
		
		
		//ricevo messaggio da server
		String risp=ricezioneMess();
		
		if(risp.equals("@ok"))
			return "ok";
		else if(risp.equals("@no,"+ComandiException.TOKEN_NON_VALIDO))
			throw new ComandiException(ComandiException.TOKEN_NON_VALIDO);
		else if(risp.equals("@no,"+ComandiException.NON_IN_PARTITA))
			throw new ComandiException(ComandiException.NON_IN_PARTITA);
		else if(risp.equals("@no,"+ComandiException.NON_IL_TUO_TURNO))
			throw new ComandiException(ComandiException.NON_IL_TUO_TURNO);	
		return null;
	}

	@Override
	public String passaTurno(String token) throws ComandiException, IOException {
		//invio messaggio a server
		String mess="@passaTurno,token="+token;
		
		bufferedWriter.write(mess);
		bufferedWriter.newLine();
		bufferedWriter.flush();
		System.out.println(socket+" ---> "+mess);
		
		//ricevo messaggio da server
		String risp=ricezioneMess();
		
		if(risp.equals("@ok"))
			return "ok";
		else if(risp.equals("@no,"+ComandiException.TOKEN_NON_VALIDO))
			throw new ComandiException(ComandiException.TOKEN_NON_VALIDO);
		else if(risp.equals("@no,"+ComandiException.NON_IN_PARTITA))
			throw new ComandiException(ComandiException.NON_IN_PARTITA);
		else if(risp.equals("@no,"+ComandiException.NON_IL_TUO_TURNO))
			throw new ComandiException(ComandiException.NON_IL_TUO_TURNO);	
		return null;
	}
	
	public String ricezioneMess(){
		String ultimaRisp=null;
		while(t.isRispOK()==false){
			try {
					synchronized(this){
						wait();
					}				
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		t.setRispOK(false);
		ultimaRisp=t.getUltimaRisp();
		return ultimaRisp;
	}

	
}
